<html>
<head>
<link rel="shortcut icon" href="./favicon.ico">
<link rel="stylesheet" type="text/css" href="./style.css">
<link rel="canonical" href="./Pipeline_Merge_One_Hot.html">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="Takes in multiple input ready/valid handshakes with associated data, and merges them one at a time into a single output ready/valid handshake. An input is merged when selected by a one-hot bit vector. (Use [Binary to One-Hot](./Binary_to_One_Hot.html) if necessary.)">
<title>Pipeline Merge One Hot</title>
</head>
<body>

<p class="inline bordered"><b><a href="./Pipeline_Merge_One_Hot.v">Source</a></b></p>
<p class="inline bordered"><b><a href="./legal.html">License</a></b></p>
<p class="inline bordered"><b><a href="./index.html">Index</a></b></p>

<h1>Pipeline Merge (One-Hot Selector)</h1>
<p>Takes in multiple input ready/valid handshakes with associated data, and
 merges them one at a time into a single output ready/valid handshake. An
 input is merged when selected by a one-hot bit vector. (Use <a href="./Binary_to_One_Hot.html">Binary to
 One-Hot</a> if necessary.)</p>
<h2>Interleaving</h2>
<p>Normally, the <code>selector</code> remains stable while input transfers are in
 progress (input ready and valid both high), but if you are careful you can
 change the selector each cycle to interleave data from multiple inputs
 transfers into the output transfer.</p>
<h2>Multiple/No selected inputs</h2>
<p>Normally, only one bit of the one-hot <code>selector</code> must be set at any time.</p>
<p>If more than one bit is set, then the multiple selected inputs are combined
 so that the output receives a Boolean reduction of the selected input
 valids (<code>HANDSHAKE_MERGE</code>), and a possibly different Boolean reduction of
 the selected input data (<code>DATA_MERGE</code>). For example, if both merge
 parameters are set to <code>"OR"</code>, and if you can guarantee that only one input
 is active at any given moment, the resulting operation is that of
 a non-synchronizing <a href="./Pipeline_Join.html">Pipeline Join</a>.</p>
<p>If no bit is set, then the inputs are all disconnected and no input
 handshake can complete, effectively forming a multi-input <a href="./Pipeline_Gate.html">Pipeline
 Gate</a>. Any pending output handshake can still
 complete.  Formally speaking, letting the output handshake proceed after an
 input handshake was accepted is necessary to not break the monotonicity
 property of Kahn Process Networks.</p>
<p>The IMPLEMENTATION parameter defaults to "AND", and controls the
 implementation of the Annullers inside the mux/demux. It is unlikely you
 will need to change it.</p>
<h2>Avoiding combinational loops</h2>
<p>As a design convention, we must avoid a combinational path between the
 valid and ready signals in a given pipeline interface, because if the other
 end of the pipeline connection also has a ready/valid combinational path,
 connecting these two interfaces will form a combinational loop, which
 cannot be analyzed for timing, or simulated reliably.</p>
<p>Thus, the output interface is buffered to break the combinational path,
 even if the buffering is redundant. It's not worth the risk of a bad
 simulation or synthesis otherwise.</p>

<pre>
`default_nettype none

module <a href="./Pipeline_Merge_One_Hot.html">Pipeline_Merge_One_Hot</a>
#(
    parameter WORD_WIDTH        = 0,
    parameter INPUT_COUNT       = 0,
    parameter HANDSHAKE_MERGE   = "",
    parameter DATA_MERGE        = "",
    parameter IMPLEMENTATION    = "AND",

    // Do not set at instantiation, except in IPI
    parameter TOTAL_WIDTH   = WORD_WIDTH * INPUT_COUNT
)
(
    input  wire                     clock,
    input  wire                     clear,

    input  wire [INPUT_COUNT-1:0]   selector,

    input  wire [INPUT_COUNT-1:0]   input_valid,
    output wire [INPUT_COUNT-1:0]   input_ready,
    input  wire [TOTAL_WIDTH-1:0]   input_data,

    output wire                     output_valid,
    input  wire                     output_ready,
    output wire [WORD_WIDTH-1:0]    output_data
);
</pre>

<p>First, pass the selected input valid to the output buffer valid.</p>

<pre>
    wire input_valid_selected;

    <a href="./Multiplexer_One_Hot.html">Multiplexer_One_Hot</a>
    #(
        .WORD_WIDTH     (1),
        .WORD_COUNT     (INPUT_COUNT),
        .OPERATION      (HANDSHAKE_MERGE),
        .IMPLEMENTATION (IMPLEMENTATION)
    )
    valid_mux
    (
        .selectors  (selector),
        .words_in   (input_valid),
        .word_out   (input_valid_selected)
    );
</pre>

<p>Select the associated input data to pass to the output buffer data.</p>

<pre>
    wire [WORD_WIDTH-1:0] input_data_selected;

    <a href="./Multiplexer_One_Hot.html">Multiplexer_One_Hot</a>
    #(
        .WORD_WIDTH     (WORD_WIDTH),
        .WORD_COUNT     (INPUT_COUNT),
        .OPERATION      (DATA_MERGE),
        .IMPLEMENTATION (IMPLEMENTATION)
    )
    data_out_mux
    (
        .selectors      (selector),
        .words_in       (input_data),
        .word_out       (input_data_selected)
    );
</pre>

<p>Steer the output buffer ready port to the selected input ready port.  Since
 this is a single-bit signal, the <code>valids_out</code> isn't necessary if we don't
 broadcast.</p>

<pre>
    wire input_ready_buffered;

    <a href="./Demultiplexer_One_Hot.html">Demultiplexer_One_Hot</a>
    #(
        .BROADCAST      (0),
        .WORD_WIDTH     (1),
        .OUTPUT_COUNT   (INPUT_COUNT),
        .IMPLEMENTATION (IMPLEMENTATION)
    )
    ready_in_demux
    (
        .selectors      (selector),
        .word_in        (input_ready_buffered),
        .words_out      (input_ready),
        // verilator lint_off PINCONNECTEMPTY
        .valids_out     ()
        // verilator lint_on  PINCONNECTEMPTY
    );
</pre>

<p>Finally, we must buffer the output interface to break the combinational
 path from valid to ready.</p>

<pre>
    <a href="./Pipeline_Skid_Buffer.html">Pipeline_Skid_Buffer</a>
    #(
        .WORD_WIDTH      (WORD_WIDTH),
        .CIRCULAR_BUFFER (0)            // Not meaningful here
    )
    output_buffer
    (
        .clock          (clock),
        .clear          (clear),
        
        .input_valid    (input_valid_selected),
        .input_ready    (input_ready_buffered),
        .input_data     (input_data_selected),
        
        .output_valid   (output_valid),
        .output_ready   (output_ready),
        .output_data    (output_data)
    );

endmodule
</pre>

<hr>
<p><a href="./index.html">Back to FPGA Design Elements</a>
<center><a href="https://fpgacpu.ca/">fpgacpu.ca</a></center>
</body>
</html>

